package com.hunter.view;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.SwingWorker;

import com.hunter.desktop.file.FileData;
import com.hunter.desktop.file.content.ContentChooser;
import com.hunter.desktop.file.content.IndexAllContentChooser;
import com.hunter.desktop.file.fetch.Chooser;
import com.hunter.desktop.file.fetch.FileFetcher;
import com.hunter.desktop.file.fetch.support.AllFile;
import com.hunter.desktop.file.fetch.support.ChooserClause;
import com.hunter.desktop.file.fetch.support.ChooserGroup;
import com.hunter.desktop.file.fetch.support.DirectoryOnly;
import com.hunter.desktop.file.fetch.support.FileOnly;
import com.hunter.desktop.file.fetch.support.PostfixFileChooser;
import com.hunter.desktop.file.fetch.support.TimeSpanChooser;
import com.hunter.desktop.file.fetch.support.ChooserClause.Occur;
import com.hunter.lucene.util.index.Writable;
import com.hunter.util.IndexManager;
import com.hunter.util.LogUtil;
import com.hunter.util.ConfigManager;
import com.hunter.util.SystemUtil;
import com.mkk.swing.SwingUtil;

/**
 * 2010-9-12 下午10:29:17<br>
 * 创建索引面板
 * 
 * @author mkk
 */
public class CreateIndexPanel extends JPanel {

	private static final long serialVersionUID = 1L;
	// settingDialog
	private SettingDialog main;
	// panel
	private JPanel panel1, panel2, panel3, panel4, panel5, panel6;
	// label
	private JLabel label1;
	// buttons
	private JButton button1, button2, button3, button4, button5, button6;
	// progressbar
	private JProgressBar bar;
	// jtextfield
	private JTextField textField1, textField2, textField3;
	// jfilechooser
	private JFileChooser chooser;
	// 索引选项
	private String[] labStrs = { "对文件名与目录信息建立索引(默认)", "对文件内容建立索引",
			"对隐藏文件与隐藏文件夹建立索引", "按时间段建立索引", "覆盖已经创建的索引文件", "对特定文件后缀名建立索引" };
	private JCheckBox boxs[] = new JCheckBox[labStrs.length];
	private JLabel labels[] = new JLabel[labStrs.length];
	private JList list1;
	private DefaultListModel listModel;
	private String[] suffixs = { "txt(文本文件)", "doc(word文档)", "xls(Excel文件)",
			"gif(gif图片)", "jpg(jpg图片)", "jpeg(jpeg图片)", "mp3(mp3音频文件)",
			"wma(wma音频文件)", "rar(rar压缩文件)", "zip(zip压缩文件)" };
	private String[] realSuffixs = { "txt", "doc", "xls", "gif", "jpg", "jpeg",
			"mp3", "wma", "rar", "zip" };
	// 保存改变后的后缀
	private List<String> suffexList = new LinkedList<String>();
	// 创建索引的目录
	private File f;
	// 日期时间值
	private Calendar startCal, endCal;

	/**
	 * constructor
	 * 
	 * @param main
	 */
	public CreateIndexPanel(SettingDialog main) {
		this.main = main;
		this.initComponents();
		this.initDatas();
		this.processEvents();
	}

	/**
	 * 初始化数据
	 */
	private void initDatas() {
		for (String s : realSuffixs) {
			this.suffexList.add(s);
		}
	}

	/**
	 * 初始组件
	 */
	private void initComponents() {
		this.setLayout(new BorderLayout());
		// north
		this.initNorthPanel();
		this.add(this.panel1, BorderLayout.NORTH);
		// center
		this.initCenterPanel();
		this.add(this.panel2, BorderLayout.CENTER);
		// south
		this.initSouthPanel();
		this.add(this.panel3, BorderLayout.SOUTH);
		// chooser
		this.chooser = new JFileChooser(
				new File(System.getProperty("user.dir")));
		this.chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
		this.chooser.setMultiSelectionEnabled(false);
		this.chooser.setApproveButtonText("确定");
		this.chooser.setDialogTitle("指定创建索引目录");
	}

	/**
	 * 南边面板
	 */
	private void initSouthPanel() {
		this.panel3 = new JPanel();
		this.panel3.setLayout(new BorderLayout(3, 3));
		bar = new JProgressBar(0, 100);
		bar.setVisible(false);
		panel3.add(bar, BorderLayout.CENTER);
		this.button1 = new JButton("创建(C)");
		button1.setMnemonic('C');
		button1.setBorder(BorderFactory.createEmptyBorder(3, 8, 3, 8));
		panel3.add(this.button1, BorderLayout.EAST);
	}

	/**
	 * 中间面板
	 */
	private void initCenterPanel() {
		this.panel2 = new JPanel();
		panel2.setLayout(new BorderLayout());
		// north
		this.panel4 = new JPanel();
		this.panel4.setLayout(new GridLayout(2, 1));
		this.label1 = new JLabel("<html>创建索引是对要进行搜索的目录信息创建索引文件,搜索依赖于索引文件,"
				+ "点此查看<a href='#'>已创建索引的目录</a>. "
				+ "注意:对于已创建索引的目录若再次创建则更新已存在的索引文件</html>");
		panel4.add(this.label1);
		JPanel panel21 = new JPanel(new FlowLayout(FlowLayout.LEFT));
		this.label1 = new JLabel("指定目录:");
		this.label1.setForeground(Color.GRAY);
		panel21.add(this.label1);
		this.textField1 = new JTextField(47);
		panel21.add(this.textField1);
		this.button2 = new JButton("浏览...");
		this.button2.setBorder(BorderFactory.createEmptyBorder(3, 5, 3, 5));
		panel21.add(this.button2);
		panel2.add(panel4, BorderLayout.NORTH);
		panel4.add(panel21);
		// center
		this.panel5 = new JPanel();
		panel5.setBorder(BorderFactory.createTitledBorder("索引选项"));
		this.panel5.setLayout(new BorderLayout(1, 1));
		JPanel panel51 = new JPanel(new GridLayout(labStrs.length, 2));
		for (int i = 0; i < this.labStrs.length; i++) {
			this.boxs[i] = new JCheckBox(this.labStrs[i]);
			this.labels[i] = new JLabel();
			this.labels[i].setForeground(Color.GRAY);
			panel51.add(boxs[i]);
			panel51.add(labels[i]);
		}
		// 设置默认索引选项
		boxs[0].setSelected(true);
		labels[3].setEnabled(false);
		panel5.add(panel51, BorderLayout.NORTH);
		JPanel panel52 = new JPanel(new BorderLayout(5, 15));
		this.list1 = new JList();
		list1.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		listModel = new DefaultListModel();
		for (String s : this.suffixs) {
			listModel.addElement(s);
		}
		list1.setModel(listModel);
		list1.setEnabled(false);
		panel52.add(new JScrollPane(list1), BorderLayout.CENTER);
		button3 = new JButton("添加");
		button4 = new JButton("修改");
		button5 = new JButton("删除");
		button6 = new JButton("设为默认");
		button3.setPreferredSize(button6.getPreferredSize());
		button4.setPreferredSize(button6.getPreferredSize());
		button5.setPreferredSize(button6.getPreferredSize());
		button3.setEnabled(false);
		button4.setEnabled(false);
		button5.setEnabled(false);
		button6.setEnabled(false);
		JPanel panel521 = new JPanel(new GridLayout(5, 1, 1, 4));
		panel521.add(button3);
		panel521.add(button4);
		panel521.add(button5);
		panel521.add(button6);
		panel521.add(new JLabel());
		panel52.add(panel521, BorderLayout.EAST);
		panel5.add(panel52, BorderLayout.CENTER);
		panel2.add(panel5, BorderLayout.CENTER);
	}

	/**
	 * 北面面板
	 */
	private void initNorthPanel() {
		this.panel1 = new JPanel();
		panel1.setLayout(new GridLayout(2, 1, 5, 5));
		JLabel label = new JLabel(" 创建索引");
		label.setFont(new Font("宋体", Font.PLAIN, 16));
		label.setForeground(new Color(0, 0, 204));
		panel1.add(label);
		JSeparator sep = new JSeparator(SwingConstants.HORIZONTAL);
		panel1.add(sep);
	}

	/**
	 * 事件处理
	 */
	private void processEvents() {
		// 创建索引事件
		this.button1.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				// 检查条件
				if (f == null) {
					main.setInfo("未指定创建索引目录!", Color.RED);
					textField1.requestFocus();
					return;
				}
				// 设为不可用
				button1.setEnabled(false);
				bar.setVisible(true);
				bar.setStringPainted(true);
				// worker
				SwingWorker<Void, Integer> worker = new SwingWorker<Void, Integer>() {

					protected Void doInBackground() throws Exception {
						try {
							bar.setString("创建索引选项...");
							publish(1);
							// 创建ChooserGroup
							List<ChooserClause> cgList = new ArrayList<ChooserClause>();
							// 隐藏文件
							if (boxs[2].isSelected()) {
								ChooserClause hidden = new ChooserClause(
										new Chooser() {
											public boolean accept(File file) {
												return file.isHidden();
											}
										}, Occur.MUST);
								cgList.add(hidden);
							}
							// 时间段
							if (boxs[3].isSelected()) {
								ChooserClause timeSpan = new ChooserClause(
										new TimeSpanChooser(startCal.getTime(),
												endCal.getTime()), Occur.MUST);
								cgList.add(timeSpan);
							}
							// 后缀名
							if (boxs[5].isSelected()) {
								ChooserClause postfixChooser = new ChooserClause(
										new PostfixFileChooser(suffexList
												.toArray(new String[0])),
										Occur.MUST);
								cgList.add(postfixChooser);
								// System.out.println(suffexList);
							}
							publish(3);
							// 文件内容
							ContentChooser contentChooser = null;
							if (boxs[1].isSelected()) {
								ChooserClause cals = new ChooserClause(
										new AllFile(), Occur.SHOULD);
								cgList.add(cals);
								contentChooser = new IndexAllContentChooser();
							}
							// 默认选项
							if (boxs[0].isSelected()) {
								ChooserClause filec = new ChooserClause(
										new FileOnly(), Occur.SHOULD);
								ChooserClause directory = new ChooserClause(
										new DirectoryOnly(), Occur.SHOULD);
								cgList.add(filec);
								cgList.add(directory);
							}

							// 覆盖已创建的索引
							boolean isCatch = boxs[4].isSelected();
							// 处理是否第一次创建
							if (!SystemUtil.isIndexFileExist()) {
								isCatch = true;
							}

							publish(5);
							bar.setString("创建ChooserGroup...");
							ChooserGroup group = new ChooserGroup();
							// 处理各种情况
							int size = cgList.size();
							// 1.没有其他选项,以默认方式构造
							if (size == 0) {
								ChooserClause filec = new ChooserClause(
										new FileOnly(), Occur.SHOULD);
								ChooserClause directory = new ChooserClause(
										new DirectoryOnly(), Occur.SHOULD);
								group.add(filec);
								group.add(directory);
							} else if (size > 0) {
								// 2.有其他选项,以指定方式构造
								for (ChooserClause cc : cgList) {
									group.add(cc);
								}
							}
							publish(7);
							bar.setString("创建FileFetcher...");
							// 构造FileFetcher
							FileFetcher fetcher = null;
							if (contentChooser != null) {
								fetcher = new FileFetcher(new File[] { f },
										group, contentChooser);
							} else {
								fetcher = new FileFetcher(new File[] { f },
										group);
							}
							// create index
							Enumeration<FileData> enumeration = fetcher
									.iterator();
							// 根据是否覆盖索引选项获取Writable
							Writable writ = ConfigManager.getManager()
									.getWriter(isCatch);
							publish(10);
							bar.setString("开始创建索引文件...");
							while (enumeration.hasMoreElements()) {
								FileData fe = enumeration.nextElement();
								bar.setString("创建索引 " + fe.getAbsolutePath());
								publish((bar.getValue() + 2) % 100);
								writ.update(fe);
							}
							// commit
							writ.commit();
							publish(98);
							// update
							ConfigManager configManager = ConfigManager
									.getManager();
							configManager.updateSearchable();
							configManager.updateSuggestionConsult();
							// 将对应的目录加入到已创建索引目录列表
							IndexManager.getIndexManager().add(
									f.getAbsolutePath());
							// 更新索引管理界面的列表信息

							main.setInfo("索引创建完成!", Color.BLUE);
						} catch (Exception e) {
							e.printStackTrace();
							// save error log
							LogUtil.saveExceptionLog(e);
							// info
							SwingUtil.showErrorInfo(main, "异常", e.getMessage());
							main.setInfo("", Color.BLUE);
						}
						return null;
					}

					protected void process(List<Integer> chunks) {
						for (int i : chunks) {
							bar.setValue(i);
						}
					}

					protected void done() {
						button1.setEnabled(true);
						bar.setVisible(false);
					}
				};
				worker.execute();
			}
		});
		// 浏览事件
		this.button2.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				int i = chooser.showOpenDialog(main);
				if (JFileChooser.APPROVE_OPTION == i) {
					f = chooser.getSelectedFile();
					textField1.setText(f.getAbsolutePath());
				}

			}
		});
		// 指定后缀选项事件
		this.boxs[boxs.length - 1].addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				boolean flag = boxs[boxs.length - 1].isSelected();
				list1.setEnabled(flag);
				button3.setEnabled(flag);
				button6.setEnabled(flag);
				if (flag) {
					labels[labels.length - 1].setText("请添加,修改或删除要创建索引的后缀名");
					if (list1.getSelectedIndex() != -1) {
						button4.setEnabled(flag);
						button5.setEnabled(flag);
					}
				} else {
					labels[labels.length - 1].setText("");
					button4.setEnabled(flag);
					button5.setEnabled(flag);
				}

			}
		});
		// list1点击事件
		list1.addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent e) {
				boolean flag = boxs[boxs.length - 1].isSelected();
				if (!flag) {
					return;
				}
				int i = list1.getSelectedIndex();
				if (i != -1) {
					button4.setEnabled(true);
					button5.setEnabled(true);
				} else {
					button4.setEnabled(false);
					button5.setEnabled(false);
				}
			}
		});
		// 覆盖创建索引文件点击事件
		boxs[4].addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				if (boxs[4].isSelected()) {
					labels[4].setText("注意:此选项将删除所有已创建的索引文件");
					labels[4].setForeground(Color.RED);
				} else {
					labels[4].setText("");
				}

			}
		});
		// 默认选项事件
		boxs[0].addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				if (!boxs[0].isSelected()) {
					labels[0].setText("建议勾选创建索引默认选项");
				} else {
					labels[0].setText("");
				}

			}
		});
		// 添加后缀
		button3.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				getSuffixPanel("", "");
				int i = SwingUtil.showConfirmInfo(CreateIndexPanel.this, "添加",
						panel6);
				if (i == JOptionPane.OK_OPTION) {
					// 判断该后缀是否存在
					String s1 = textField2.getText().trim();
					String s2 = textField3.getText().trim();
					if (s1.length() == 0) {
						labels[5].setText("后缀为空,添加失败!");
						return;
					}
					if (addSuffix(s1, s2)) {
						labels[5].setText("添加后缀 " + s1 + "成功!");
					} else {
						labels[5].setText("添加失败,该后缀名已存在!");
					}
				}
			}
		});
		// 修改后缀
		button4.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				int i = list1.getSelectedIndex();
				if (i == -1) {
					return;
				}
				String s = list1.getSelectedValue().toString();
				String name = null;
				String desc = "";
				if (s.contains("(")) {
					name = s.substring(0, s.indexOf("("));
					desc = s.substring(s.indexOf("(") + 1, s.length() - 1);
				} else {
					name = s;
				}
				getSuffixPanel(name, desc);
				int k = SwingUtil.showConfirmInfo(CreateIndexPanel.this, "修改",
						panel6);
				if (k == JOptionPane.OK_OPTION) {
					// 判断该后缀是否存在
					String s1 = textField2.getText().trim();
					String s2 = textField3.getText().trim();
					if (s1.length() == 0) {
						labels[5].setText("后缀名为空,修改失败!");
						return;
					}
					listModel.remove(i);
					if (addSuffix(s1, s2)) {
						labels[5].setText("修改后缀 " + s1 + "成功!");
					} else {
						labels[5].setText("修改失败!");
					}
				}
			}
		});
		// 删除后缀
		button5.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				int i = list1.getSelectedIndex();
				if (i == -1) {
					return;
				}
				String s = (String) list1.getSelectedValue();
				if (s.contains("(")) {
					s = s.substring(0, s.indexOf("("));
				}
				suffexList.remove(s);
				listModel.remove(i);
				if (listModel.size() == 0) {
					// 设为不可用
					button3.setEnabled(false);
					button4.setEnabled(false);
					button5.setEnabled(false);
					button6.setEnabled(false);
					list1.setEnabled(false);
					boxs[5].setSelected(false);
					labels[5].setText("");
				}
			}
		});
		// 默认
		button6.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				listModel.removeAllElements();
				for (String s : suffixs) {
					listModel.addElement(s);
				}
				// real default
				suffexList.clear();
				suffexList.addAll(Arrays.asList(realSuffixs));
			}
		});
		// 时间选项
		boxs[3].addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				if (boxs[3].isSelected()) {
					// 设置时间段
					labels[3].setEnabled(true);
					labels[3].setCursor(Cursor
							.getPredefinedCursor(Cursor.HAND_CURSOR));
					labels[3].setText("<html>点此<a href=''#>设置</a>索引时间段</html>");
				} else {
					// hidden
					labels[3].setText("");
					labels[3].setEnabled(false);
				}
			}
		});
		// 时间选项设置
		labels[3].addMouseListener(new MouseAdapter() {

			public void mouseClicked(MouseEvent e) {
				// 弹出设置页面
				Point p = e.getLocationOnScreen();
				p.y = p.y - 20;
				SetTimeDialog dia = new SetTimeDialog(main, true);
				dia.setLocation(p);
				dia.setVisible(true);
				startCal = dia.getStart();
				endCal = dia.getEnd();
				StringBuilder sb = new StringBuilder("<html>");
				sb.append(SystemUtil.formatCalendar(startCal));
				sb.append(" 至 ");
				sb.append(SystemUtil.formatCalendar(endCal));
				sb.append(" <a href='#'>修改</a></html>");
				labels[3].setText(sb.toString());
			}
		});

	}

	/**
	 * 添加后缀
	 * 
	 * @param name
	 * @param desc
	 * @return
	 */
	private boolean addSuffix(String name, String desc) {
		for (int i = 0; i < listModel.getSize(); i++) {
			if (listModel.get(i).toString().equalsIgnoreCase(name)) {
				return false;
			}
		}
		// add real suffix
		suffexList.add(name);
		if (desc.length() > 0) {
			listModel.addElement(name + "(" + desc + ")");
		} else {
			listModel.addElement(name);
		}
		return true;
	}

	/**
	 * 获取添加或修改后缀名的面板
	 * 
	 * @param name
	 * @param desc
	 */
	private void getSuffixPanel(String name, String desc) {
		if (this.panel6 == null) {
			panel6 = new JPanel(new BorderLayout());
			JPanel p61 = new JPanel(new FlowLayout(FlowLayout.RIGHT));
			p61.add(new JLabel("后缀名:"));
			this.textField2 = new JTextField(name, 20);
			p61.add(this.textField2);
			panel6.add(p61, BorderLayout.NORTH);
			JPanel p62 = new JPanel(new FlowLayout(FlowLayout.RIGHT));
			p62.add(new JLabel("描述:"));
			this.textField3 = new JTextField(desc, 20);
			p62.add(this.textField3);
			panel6.add(p62, BorderLayout.CENTER);
		}
		textField2.setText(name);
		textField3.setText(desc);
	}
}
